package GUI;


import dao.FileMeta;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Window;
import service.SearchService;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;


/**
 *  Initializable 可初始化
 */
public class GUIController implements Initializable {

    /**
     *  这里的注解以及实例化对象,都是为了和 app.fxml 文件中的控件关联起来
     *  注意包的位置 , 来自 javafx.xxxx
     */
    @FXML // 注解是为了和 FX 中的控件进行关联, 对象名字要和 .fxml 中的 fx:id 对应上
    private Label label2;  // 注意包的位置

    @FXML
    private GridPane gridPane;

    @FXML
    private Button button;

    @FXML
    private Label label;

    @FXML
    private TextField textField;

//    @FXML
//    private TableView name2;

    /**
     *  注意 controller 类中,不一定非得是界面上的元素,如这些 @FXML 注解的,还可以有这些普通的 service
     *  这里只是声明一个对象变量,还没有实例化呢,也就是一个引用，指向内存中的某个位置，但这个位置并没有被初始化成任何实际的对象。
     *  该对象实际上还没有被创建
     */
    private SearchService searchService;

    /**
     *  注意 TableView 表示一个表格,里面有很多行,每一行又有很多列
     *  此处就把 TableView 视为一个集合类
     *  这里的每一个元素都是一个对象,元素的对象里的元素,就和界面表格这里的列相匹配
     */
    @FXML
    private TableView<FileMeta> tableView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        // TextField textField = new TextField(); 前面已经创建对应关系了
        // 这是设置搜索框中初始默认显示的内容
        textField.setPromptText("请先指定要查找文件所在的目录，否则不能检索，且支持汉字首字母搜索，如小夜：xy");

        /**
         *  TODO 设置表格可左右伸缩未做
         */
        // 设置表格列的可伸缩性策略为 UNCONSTRAINED_RESIZE_POLICY
        // name2.setResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
        // tableView.setColumnResizePolicy(name2,true);

        // System.out.println(label2.getText());
        // label2.setText("修改之后");
        // 在初始化操作中 , 给输入框中 textField 加入一个监听器
        // 需要指定,是针对 text 这个内容属性来进行监听,(监听哪些内容) 因为有很多变化都会被监听到,比如 焦点,尺寸大小变化
        textField.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                // 这里 observable 观察者对象不用管,重点用到后两个参数
                // oldValue 是改动之前的
                // newValue 是改动之后的
                flashTable(newValue);
            }
        });
    }

    /**
     *  刷新表格中的内容，根据输出的改变，实时改变表格内容
     * @param query
     */
    private void flashTable(String query) {
        // 重新查询数据库,把查询结果,设置到表格中去,自动显示的,添加内容之后,就会自动显示内容,还有自动生成滚动条
        // 查询就依赖于 service 类
        if (searchService == null) {
            System.out.println("searchService 未初始化,不能查询!");
            return;
        }
        // 先把表格中之前的内容给清空,需要拿到表格 tableView 中的内容
        // ObservableList 就类似于 list
        ObservableList<FileMeta> fileMetas = tableView.getItems();
        // 清空之前的内容
        fileMetas.clear();

        List<FileMeta> resultList = searchService.search(query);
        // 把查询结果添加到 tableView 中,因为 fileMetas 就是之前获取到 tableView 中的内容
        // 所以直接添加到 fileMetas 中, 就是添加到 tableView 中
        fileMetas.addAll(resultList);
    }

    /**
     * 使用这个方法,作为鼠标的点击事件,需要有一个 MouseEvent 参数,注意包的位置是 JavaFX
     * 当前可能用不到这个参数,但是定义方法的时候还是得有这个参数
     *
     * 把这个方法 和 fxml 文件中的按钮控件关联在一起
     * fxml 中,属性为 onMouseClicked ="#chooseDirectory" , 注意名字对应上
     * @param mouseEvent
     */
    public void chooseDirectory(MouseEvent mouseEvent) {
        // System.out.println("鼠标点击");
        // 如何实现点击按钮之后,弹出一个对话框选择文件呢?
        // JavaFX 已经帮我们封装好了,提供了一个 DirectoryChooser 类
        // 只需要创建出来实例,并且这个选择文件框显示出来就可以了

        // 1.先创建出来一个目录选择器
        DirectoryChooser directoryChooser = new DirectoryChooser();

        // 上面这是创建好了,还得是弹出对话框
        // 界面上弹出一个对话框,就得明确这个对话框是哪个窗口弹得
        // (对话框得有一个父窗口)
        // 此时就选用主程序的窗口,来作为父窗口
        // 为啥弹出对话框,要指定"父窗口呢"
        // 这也是系统的一个小要求,弹出对话框之后,必须要把对话框中的东西选好,然后才能操作父窗口
        // 如果还没选完呢,此时父窗口就是不可选中的状态,称为"模态对话框"


        /*FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("选择文件");
        // 显示选择框
        fileChooser.showOpenDialog(null);*/

        // 2.显示出来选择目录框
        Window window = gridPane.getScene().getWindow();
        // 选择的结果可以用 File 对象来接收
        File file = directoryChooser.showDialog(window);
        if(file == null) {
            System.out.println("未选择目录");
            // 什么也不做直接返回
            return;
        }

        // 3.让用户选择的目录,显示到 label 标签中去
        System.out.println(file.getAbsoluteFile());
        label.setText(file.getAbsolutePath());

        // 4.判定一下当前 service 是否为空,如果非空,说明不是首次扫描
        // 就应该停止上次的扫描任务
        if (searchService != null) {
            searchService.shutdown();
        }

        // 让用户选择路径,希望程序对指定路径进行扫描,把对应的数据加入到数据库中去
        searchService = new SearchService();
        searchService.init(file.getAbsolutePath());
    }

    /**
     *  新添加：双击事件
     *
     *
     *  实现shuang击表格中的路径之后可以复制到剪切板
     *  参考星火 实现 ：JavaFX 中的表格中的内容怎么做才可以复制，并举例说明
     *  之后拿到核心代码：Clipboard clipboard = Clipboard.getSystemClipboard();
     *                  ClipboardContent content = new ClipboardContent();
     *                  content.putString(copyPath);
     *                  clipboard.setContent(content);
     *
     *  改进：双击可直接打开文件所在目录
     *
     * @param mouseEvent
     */
    public void copyContent(MouseEvent mouseEvent) {

        // 表示双击事件， == 1 就是点击事件
        if(2 == mouseEvent.getClickCount()) {

            // 星火：获取用户在 TableView 控件中当前选中的项
            FileMeta fileMeta = tableView.getSelectionModel().getSelectedItem();
            if(fileMeta != null) {
                // 带上名字就是直接打开了，应该是到文件所在目录，是否打开由用户决定
                // String copyPath = fileMeta.getPath() + "\\"+fileMeta.getName();

                // 获取文件路径并转换为URI
                // URI uri = new File(fileMeta.getPath()).toURI();
                // 打开文件夹
                Desktop desktop = Desktop.getDesktop();

                // 创建一个文件
                File dirToOpen = new File(fileMeta.getPath());

                try {
                    // 打开文件所在的路径，文件不存在，或者路径不存在会异常
                    desktop.open(dirToOpen);
                } catch (IOException e) {
                    e.printStackTrace();
                }


                String copyPath = fileMeta.getPath();
//                /**
//                 *  接下来是把字符串复制到系统剪切板的方法
//                 *  注意包的位置，Clipboard ： import javafx.scene.input.Clipboard;
//                 *
//                 *  这段代码是Java中用于将字符串复制到系统剪贴板的方法。
//                 * 首先，Clipboard clipboard = Clipboard.getSystemClipboard();这行代码获取了系统剪贴板的一个实例。
//                 * 然后，ClipboardContent content = new ClipboardContent();这行代码创建了一个新的剪贴板内容对象。
//                 * 接着，content.putString(cellContent);这行代码将字符串cellContent放入剪贴板内容对象中。
//                 * 最后，clipboard.setContent(content);这行代码将剪贴板内容对象设置为系统剪贴板的内容。
//                 * 这样，cellContent字符串就被复制到了系统剪贴板，可以在其他地方粘贴出来。例如，如果你在一个文本编辑器中输入了一段文字，
//                 * 然后运行这段代码，那么这段文字就会被复制到你打开的任何其他程序中。
//                 */
//                Clipboard clipboard = Clipboard.getSystemClipboard(); // 实例化剪切板对象
//                ClipboardContent content = new ClipboardContent(); // 实例化剪切板内容的对象，之后把这个设置到剪切板对象里去
//                content.putString(copyPath);   // 把字符串内容放到剪切板内容对象中去
//                clipboard.setContent(content); // 将剪切板内容对象设置为剪切板的内容
//
//                /**
//                 *  实现点击复制后弹窗提示已复制
//                 */
//
//                // 创建一个 Alert 对象，并设置标题、头部文本和内容文本
//                Alert alert = new Alert(Alert.AlertType.INFORMATION);
//                alert.setTitle("提示");
//                // alert.setHeaderText("这是一个提示框");
//                alert.setContentText("已复制文件名所在路径： " + copyPath);
//
//                System.out.println("");
//
//                // 添加一个确定按钮，点击后关闭提示框
//                //alert.getButtonTypes().add(ButtonType.OK);
//
//                // 显示提示框
//                alert.show();

                System.out.println("以弹窗提示，路径： " + copyPath);
            }
        }
    }
}
